﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CadDotNetTools
{
    public static class LayerTools
    {
        /// <summary>
        /// 获取图层名
        /// </summary>
        /// <param name="trans">Transaction</param>
        /// <param name="doc">Document</param>
        /// <returns></returns>
        public static List<string> GetAllLayerName(this Transaction trans, Document doc)
        {
            // 获取当前数据库
            var db = doc.Database;
            var layerNameList = new List<string>();

            // 打开图层表
            var lt = trans.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;

            // 遍历图层表
            foreach (ObjectId id in lt)
            {
                var ltr = trans.GetObject(id, OpenMode.ForRead) as LayerTableRecord;
                // 图层名称
                layerNameList.Add(ltr.Name);
            }
            return layerNameList;
        }
        /// <summary>
        /// 创建一个新的图层
        /// </summary>
        /// <param name="db">Database</param>
        /// <param name="layerName">图层名</param>
        /// <returns></returns>
        public static ObjectId AddLayer(this Database db, string layerName)
        {
            //打开层表
            var lt = db.LayerTableId.GetObject(OpenMode.ForRead) as LayerTable;
            //如果不存在名为layerName的图层，则新建一个图层o
            if (!lt.Has(layerName))
            {
                //定义一个新的图层记录
                var ltr = new LayerTableRecord();
                ltr.Name = layerName;  //设置图层名   
                //切换层表的状态为写为添加的新图层
                lt.UpgradeOpen();
                //将层表记录的信息添加到层表中
                lt.Add(ltr);
                //把层表记录添加到事物处理中
                db.TransactionManager.AddNewlyCreatedDBObject(ltr, true);
                //为了安全，将层表的状态切换为读
                lt.DowngradeOpen();
            }
            return lt[layerName];  //返回新添加的层表记录的ObjectId
        }
        /// <summary>
        /// 添加图层
        /// </summary>
        /// <param name="layName"></param>
        /// <param name="Index"></param>
        public static void AddLayer(this string layName, int Index)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            string LayerName = "";
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForWrite);
                if (lt.Has(layName))
                {
                    ed.WriteMessage($"\n <{layName}>图层已存在！");
                }
                else
                {
                    LayerName = layName;
                    LayerTableRecord ltr = new LayerTableRecord();
                    ltr.Name = LayerName;

                    //short indexColor = (short)(Index % 256);
                    short indexColor = (short)(Index);
                    ltr.Color = Color.FromColorIndex(ColorMethod.ByLayer, indexColor);
                    ObjectId layerId = lt.Add(ltr);
                    trans.AddNewlyCreatedDBObject(ltr, true);
                    db.Clayer = layerId;
                }

                trans.Commit();
            }

        }
        /// <summary>
        /// 修改指定图层的颜色
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="layerName">图层名</param>
        /// <param name="colorIndex">颜色索引值</param>
        /// <returns>设置图层是否成功</returns>
        public static bool SetLayerColor(this Database db, string layerName, short colorIndex)
        {
            //打开层表
            var lt = db.LayerTableId.GetObject(OpenMode.ForRead) as LayerTable;
            //如果不存在名为layerName的图层，则返回
            if (!lt.Has(layerName)) return false;
            //获取名为layerName的层表记录的Id
            var layerId = lt[layerName];
            //以写的方式打开名为layerName的层表记录
            var ltr = layerId.GetObject(OpenMode.ForWrite) as LayerTableRecord;
            //设置颜色
            ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex);
            //为了安全，将图层的状态切换为读
            ltr.DowngradeOpen();
            return true;  //设置图层颜色成功
        }
        /// <summary>
        /// 获取当前图形中所有的图层
        /// </summary>
        /// <param name="db"></param>
        /// <returns></returns>
        public static List<LayerTableRecord> GetAllLayers(this Database db)
        {
            //打开层表
            var lt = db.LayerTableId.GetObject(OpenMode.ForRead) as LayerTable;
            //用于返回层表记录的列表
            var ltrs = new List<LayerTableRecord>();
            //遍历层表
            foreach (var id in lt)
            {
                //打开层表记录
                var ltr = id.GetObject(OpenMode.ForRead) as LayerTableRecord;
                ltrs.Add(ltr);  //添加到返回列表中
            }
            return ltrs;    //返回所有的图层记录
        }
        /// <summary>
        /// 删除指定名称的图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="layerName">要删除的图层名</param>
        /// <returns></returns>
        public static bool DeleteLayer(this Database db, string layerName)
        {
            //打开层表
            var lt = db.LayerTableId.GetObject(OpenMode.ForRead) as LayerTable;
            //如果层名为0或Defpoints,则返回（这两个图层不能删除）
            if (layerName == "0" || layerName == "Defpoints") return false;
            //如果不存在名为 layerName 的图层，则返回
            if (!lt.Has(layerName)) return false;
            //获取名为layerName的层表记录的Id
            var layerId = lt[layerName];
            //如果要删除的图层为当前图层，则返回（不能删除当前图层）
            if (layerId == db.Clayer) return false;
            //打开名为layer Name的层表记录
            var ltr = layerId.GetObject(OpenMode.ForRead) as LayerTableRecord;
            //如果要删除的图层包含对象或依赖外部参照，则返回（—不能删除这些图层—）
            lt.GenerateUsageData();
            if (ltr.IsUsed) return false;
            //切换层表记录为写状态
            ltr.UpgradeOpen();
            //删除名为layerName的图层
            ltr.Erase(true);
            return true; ;//删除图层成功
        }
    }
}
